package org.jeecg.common.util.encryption;

import io.swagger.models.auth.In;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.codec.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * @Description: AES 加密
 * @author: jeecg-boot
 * @date: 2022/3/30 11:48
 */
public class AesEncryptUtil {

    /**
     * 使用AES-128-CBC加密模式 key和iv可以相同
     */
    private static String KEY = EncryptedString.key;
    private static String IV = EncryptedString.iv;

    /**
     * 加密方法
     * @param data  要加密的数据
     * @param key 加密key
     * @param iv 加密iv
     * @return 加密的结果
     * @throws Exception
     */
    public static String encrypt(String data, String key, String iv) throws Exception {
        try {

            //"算法/模式/补码方式"NoPadding PkcsPadding
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();

            byte[] dataBytes = data.getBytes();
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }

            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);

            return Base64.encodeToString(encrypted);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解密方法
     * @param data 要解密的数据
     * @param key  解密key
     * @param iv 解密iv
     * @return 解密的结果
     * @throws Exception
     */
    public static String desEncrypt(String data, String key, String iv) throws Exception {
        //update-begin-author:taoyan date:2022-5-23 for:VUEN-1084 【vue3】online表单测试发现的新问题 6、解密报错 ---解码失败应该把异常抛出去，在外面处理
        byte[] encrypted1 = Base64.decode(data);

        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

        byte[] original = cipher.doFinal(encrypted1);
        String originalString = new String(original);
        //加密解码后的字符串会出现\u0000
        return originalString.replaceAll("\\u0000", "");
        //update-end-author:taoyan date:2022-5-23 for:VUEN-1084 【vue3】online表单测试发现的新问题 6、解密报错 ---解码失败应该把异常抛出去，在外面处理
    }

    /**
     * 使用默认的key和iv加密
     * @param data
     * @return
     * @throws Exception
     */
    public static String encrypt(String data) throws Exception {
        return encrypt(data, KEY, IV);
    }

    /**
     * 使用默认的key和iv解密
     * @param data
     * @return
     * @throws Exception
     */
    public static String desEncrypt(String data) throws Exception {
        return desEncrypt(data, KEY, IV);
    }


    /**
     * bytes 转换十六进制
     * @param bytes
     * @return
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02x", bytes[i]));
        }
        return sb.toString();
    }

    /**
     * 把字符串反转，按pos位来反转
     * @param str
     * @param pos
     */
    public static String reversalStrByPos(String str, Integer pos){
        if(StringUtils.isEmpty(str)){
            return str;
        }

        if(null == pos){
            pos = 1;
        }

        char[] chars = str.toCharArray();
        char[] rsStr = new char[chars.length];
        char[] tempStr = new char[pos];
        int index = 0;
        int indexPos = 0;
        for (int i = chars.length -1; i >= 0; i--) {
            tempStr[indexPos] = chars[i];
            index++;
            indexPos++;
            if(indexPos == pos){
                indexPos = 0;
                reversalCopyStrArray(tempStr,rsStr,index-pos);
            }
        }
        return new String(rsStr);

    }


    /**
     * 从指定位置字符复制 并反转
     * @param source
     * @param target
     */
    public static char[] reversalCopyStrArray(char[]source, char[] target,Integer targetIndex){
        if(null == target || target.length < targetIndex){
            return null;
        }

        int index = targetIndex;
        for (int i = source.length -1; i >= 0; i--) {
            target[index] = source[i];
            index++;
        }
        return target;
    }




   /**
    * 测试
    */
   public static void main(String args[]) throws Exception {

       String b64 = "aBAIk5eEV0BXZghEAAYnAEIhNQ6BiwEjDgMADzQ2MDExMzE0NzM0MjY5OCQFKRIzWSAiCCUAAQwXAAEkBSkSM1kCAAAAAAAAAAAAAAAAAAAAWxY=";
       b64="aBAIk5eEV0BXZghEAAYnAEIhQA6BiwEjDAMADzQ2MDExMzE0NzM0MjY5OCQGCBEwJiAiCCUAAQwXAAEkBggRMCYCAAAAAAAAAAAAAAAAAAAAABY=";
        // b64="aBAIk5eEV0BXZggEAA4BAAHvFg==";
       byte[] encrypted1 = Base64.decode(b64);
       String s = bytesToHex(encrypted1);
       System.out.println(s);

       String readStr = s.substring(116); //上传抄表数据
       String timesStr = readStr.substring(0, 2); //上传抄表数据记录数
       int times = Integer.parseInt(timesStr);
       System.out.println(times);

           String readTimesStr = readStr.substring(2, 46);// 第一次抄表读数报文
           System.out.println("第一次抄表读数报文:"+ readTimesStr);
           String readDate = readTimesStr.substring(0, 12); // 抄表日期
           // 抄表读数 -是从低位到高位，需要两位两位来取反 0200 0000 -> 0000 0002
       //
           String readDataHex = readTimesStr.substring(12, 20);


       String reversal = reversalStrByPos(readDataHex, 2);

       int readData = Integer.parseInt(reversal, 16); // 16进制读数转10进制
           int readNumber = readData / 100;
       System.out.println(reversal);
       System.out.println(readData);
       System.out.println(readNumber);

       // String hex = "11"; // 输入的16进制数
       // int decimal = Integer.parseInt(hex, 16); // 使用Integer.parseInt()方法进行转换
       // System.out.println(decimal); // 输出转换后的10进制数
       //

       // String test1 = "sa";
       // String test =new String(test1.getBytes(),"UTF-8");
       // String data = null;
       // String key =  KEY;
       // String iv = IV;
       // // /g2wzfqvMOeazgtsUVbq1kmJawROa6mcRAzwG1/GeJ4=
       // data = encrypt(test, key, iv);
       // System.out.println("数据："+test);
       // System.out.println("加密："+data);
       // String jiemi =desEncrypt(data, key, iv).trim();
       // System.out.println("解密："+jiemi);
   }

}
